#include "fmc.h"
#include <stdarg.h>
#include "tim.h"



#define FLASH_SECTOR_11_BASE (const volatile uint8_t*)0x80E0000UL
#define FLASH_SECTOR_11_SIZE 0x20000UL

void read_memory(uint32_t address, uint8_t *data, uint32_t data_num);
uint32_t read_word(uint32_t address);
bool FLASH_Program(uint32_t WRITE_START_ADDR, uint32_t Size, uint32_t *data);
bool config_erase(void){
    //uint32_t mask = cpu_enter_critical();
    fmc_unlock();
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
    int x= fmc_sector_erase(CTL_SECTOR_NUMBER_11);
    printf("fmc_sector_erase:%d\r\n",x);
    delay_1ms(1);
    fmc_lock();
    return x;
    //cpu_exit_critical(mask);
}

bool config_load(int num,...){
    //uint32_t mask = cpu_enter_critical();
    uint32_t length = read_word(FLASH_SECTOR_11_BASE);

    if(length==0xFFFFFFFF){
        printf("blank memory");
        return false;
    }
    printf("FLASH_SECTOR_11_BASE: %d\r\n",length);delay_1ms(1);

    va_list arg_ptr;
    uint32_t param1,param2;
    uint32_t num_ = num,
            sum=0;
    va_start(arg_ptr, num);
    while(num_--){
        param1=va_arg(arg_ptr, uint32_t);
        param2=va_arg(arg_ptr, uint32_t);
        sum+=param2;
    }
    printf("sum = %d\r\n",sum);delay_1ms(1);
    if(sum!=length){
        printf("sum!=length\r\n");delay_1ms(1);
        return false;
    }

    uint32_t offset= 4;
    num_=num;
    va_start(arg_ptr, num);
    while(num_--){
        param1=va_arg(arg_ptr, uint32_t);
        param2=va_arg(arg_ptr, uint32_t);
        printf("param1=%d param2=%d\r\n",param1,param2);
        //memcpy();
        delay_1ms(1);
    }
    va_end(arg_ptr);
    //cpu_exit_critical(mask);
}

bool config_save(int num,...){
    //uint32_t mask = cpu_enter_critical();
    va_list arg_ptr;
    uint32_t param1,param2;
    uint32_t offest =0;
    va_start(arg_ptr, num);

    config_erase();
    while(num--)
    {
        param1=va_arg(arg_ptr, uint32_t);
        param2=va_arg(arg_ptr, uint32_t);
        FLASH_Program(FLASH_SECTOR_11_BASE+offest+4,param2,param1);
        offest+=param2;
        delay_1ms(10);
        printf("num:%d param1=%d param2=%d offest=%d\r\n",num,param1,param2,offest);
        delay_1ms(10);
    }
    fmc_unlock();
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
    fmc_word_program(FLASH_SECTOR_11_BASE,offest);
    delay_1ms(1);
    fmc_lock();
    printf("config_save\r\n");
    va_end(arg_ptr);

    //cpu_exit_critical(mask);
}


void read_memory(uint32_t address, uint8_t *data, uint32_t data_num)
{
    uint32_t i;
    uint8_t *p = (uint8_t *)address;
    for(i = 0; i < data_num; i++){
        data[i] = *p;
        p++;
    }
}

uint32_t read_word(uint32_t address){
    return *((uint32_t*)address);
}


bool FLASH_Program(uint32_t WRITE_START_ADDR, uint32_t Size, uint32_t *data)
{
    uint32_t Address;
    bool TransferStatus = false;
    uint32_t i;
    TransferStatus = true;
    /* Unlock the Flash Bank1 Program Erase controller */
    fmc_unlock();
    
    /* Clear All pending flags */
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
    
    
    /* Program Flash Bank1 */
    Address = WRITE_START_ADDR;
    i = 0;
    while(Address < (WRITE_START_ADDR + Size))
    {
        fmc_word_program(Address, data[i]);
        i++;
        Address = Address + 4; 
        fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
    }
    
    fmc_lock();
    
    return TransferStatus;
}



